package com.freesky.quartz.task;

import cn.hutool.core.date.DateUtil;
import cn.hutool.http.Header;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.freesky.biz.abchina.domain.LifepayBillEntity;
import com.freesky.biz.abchina.domain.LifepayOrderEntity;
import com.freesky.biz.abchina.pojo.DownloadTraceRequest;
import com.freesky.biz.abchina.service.AbChinaLifePayService;
import com.freesky.biz.abchina.service.ILifepayBillService;
import com.freesky.biz.abchina.service.ILifepayOrderService;
import com.freesky.biz.utils.SeqUtil;
import com.freesky.common.config.Constant;
import com.freesky.common.core.domain.AjaxResult;
import com.freesky.common.utils.StringUtils;
import com.freesky.framework.web.service.SendAlarmService;
import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 福建农行生活缴费每天晚上对账单模块
 */
@Component("lifePayBillTask")
public class AbChinaLifePayBillTask {
    private static final Logger logger = LoggerFactory.getLogger(AbChinaLifePayBillTask.class);

    private String PREFIX_URL = "https://enjoy.abchina.com/jf-openapiweb/";

    @Autowired
    private AbChinaLifePayService lifePayService;

    @Autowired
    private ILifepayBillService lifepayBillService;

    @Autowired
    private ILifepayOrderService lifepayOrderService;

    @Autowired
    private SendAlarmService sendAlarmService;

    public void taskProcess() {
        logger.info("lifePayBillTask task start");
        String billDate = DateUtil.format(DateUtil.offsetDay(new Date(), -1),"yyyyMMdd");

        AjaxResult ajaxResult = downloadTrace("103881310002615",billDate);
        if(ajaxResult.isSuccess()) {
            sendResultToMail();
            //sendAlarmService.sendAlarmMail(Constant.ALARM_MAIL, "福建农行生活缴费每天晚上对账单处理完成", billDate);
        } else {
            sendAlarmService.sendAlarmMail(Constant.ALARM_MAIL,"【异常】平台-福建农行生活缴费" + billDate + "对账单处理失败",ajaxResult.getMsg());
        }

    }

    //缴费对账单下载接口
    public AjaxResult downloadTrace(String merchantId, String billDate){
        try {
            //创建发送请求对象
            DownloadTraceRequest req = new DownloadTraceRequest();
            //以系统当前时间为时间戳
            String timeStamp = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date());

            //封装数据格式为json格式 固定
            req.setFormat("json");
            // 关联交易的交易序列号需由第三方提供，且必须按照特定规则上送缴费中心，规则定义：BRIDGE前缀+当前17位时间戳timeStamp+商户号merchantId
            req.getMessage().getHead().setTransSeqNum("BRIDGE"+timeStamp+merchantId);
            //交易码，固定
            req.getMessage().getHead().setTransCode("downloadTrace");
            //上下行标志 固定
            req.getMessage().getHead().setTransFlag("01");
            //时间戳格式 yyyyMMddHHmmssSSS，
            req.getMessage().getHead().setTimeStamp(timeStamp);

            //对账单文件格式 固定值：CSV（大写）或GZ
            req.getMessage().getInfo().setFileType("CSV");
            //编码格式 固定值：UTF-8（大写）
            req.getMessage().getInfo().setCharset("UTF-8");
            //缴费中心商户编号，以商户为唯一维度来下载对账单
            req.getMessage().getInfo().setMerchantId(merchantId);
            //例如 ：req.getMessage().getInfo().setMerchantId("103881104410001");
            try {
                //指定对账单的下载日期  跟下载的交易流水交易日期对应,格式yyyyMMdd
                req.getMessage().getInfo().setBillDate(billDate);
            } catch (Exception e) {
                logger.info("获取日期异常");
                e.printStackTrace();
            }
            //对账单类型billType有两个选项：
            //	ALL：暂不提供+
            //	SUCCESS：下载所有支付成功流水及所有退款成功流水，对应缴费状态为1、5、6、4，退款SUCCESS
            req.getMessage().getInfo().setBillType("SUCCESS");

            //将封装的请求对象转化为json格式
            String reqJson = JSON.toJSONString(req);
            logger.info("加密前发送的请求报文：" + reqJson);
            //加签名
            String signatrue = lifePayService.signWhithsha1withrsa(reqJson);
            //拼接发送的报文信息
            String reqStr = signatrue+"||"+ Base64.encodeBase64String(reqJson.getBytes("utf-8"));
            logger.info("发送的请求报文：" + reqStr);

            //发送签名信息获取返回签名信息
            String reqUrl = PREFIX_URL + "mchtFile/downloadTrace";
            //发送签名信息获取返回签名信息
            HttpResponse httpResponse = HttpRequest.post(reqUrl)
                    .header(Header.USER_AGENT, "Chrome")
                    .header(Header.CONTENT_TYPE,"application/json")
                    .charset("utf8")
                    .body(reqStr)
                    .timeout(10000)
                    .execute();
            // 获取返回报文
            String responseStr = "";
            if(httpResponse.bodyBytes().length > 2028){
                responseStr = httpResponse.body().substring(0,2048);
            } else {
                responseStr = httpResponse.body();
            }
            //logger.info("接收到的报文："+responseStr);
            //如果系统返回未加密异常则会返回"{"+json+"}"
            if (responseStr.startsWith("{\"string\":")) {
                return AjaxResult.error(responseStr.substring(responseStr.indexOf(":")+2,responseStr.indexOf("}")));
            } else if (responseStr.contains("||")) {
                //截取签名信息
                String headSub = responseStr.substring(0, responseStr.indexOf("||"));
                logger.warn("获取签名的前半部分："+headSub);
                //截取加密的json信息，进行解密
                String tailSub = responseStr.substring(responseStr.indexOf("||")+2);
                logger.warn("获取签名的后半部分："+tailSub);
                //将获取到的json报文进行解析，获取报文体信息
                responseStr = new String(Base64.decodeBase64(tailSub));
                logger.warn("获取签名解密后："+responseStr);
                return AjaxResult.error(responseStr);
            }


            String csvSplitBy = ",";
            BufferedReader reader = new BufferedReader(new InputStreamReader(httpResponse.bodyStream()));
            String line;
            long totalRecord = 0;
            long payRecord = 0;
            long refundRecord = 0;
            boolean payReadFlag = false;
            boolean refundReadFlag = false;

            List<LifepayBillEntity> lifepayBillList = new ArrayList<>();

            while ((line = reader.readLine()) != null) {
                //System.out.println(line); // 打印每一行数据
                // 改进点：处理字段末尾的逗号
                List<String> fields = Arrays.stream(line.split("\\|"))
                        .map(s -> {
                            // 移除末尾逗号和前后空格
                            String cleaned = s.replaceAll(",+$", "").trim();
                            // 处理特殊空值情况
                            return cleaned.isEmpty() ? "" : cleaned;
                        }).collect(Collectors.toList());

                fields.remove(0);

                System.out.println(JSON.toJSONString(fields));

                if("交易日期".equalsIgnoreCase(fields.get(0))){
                    continue;
                }

                if("商户号".equalsIgnoreCase(fields.get(0)) && "缴费成功总记录数".equalsIgnoreCase(fields.get(1))){
                    payReadFlag = true;
                    continue;
                }

                if("商户号".equalsIgnoreCase(fields.get(0)) && "退款成功总记录数".equalsIgnoreCase(fields.get(1))){
                    refundReadFlag = true;
                    continue;
                }

                if(payReadFlag){
                    payReadFlag = false;
                    long readPayNum = Long.parseLong(fields.get(1));
                    if(readPayNum != payRecord){
                        sendAlarmService.sendAlarmMail(Constant.ALARM_MAIL,"【异常】福建农行生活缴费每天晚上对账单处理，支付记录条数不对",
                                billDate +","+readPayNum+","+payRecord);
                    }
                    continue;
                }

                if(refundReadFlag){
                    refundReadFlag = false;
                    long readRefundNum = Long.parseLong(fields.get(1));
                    if(readRefundNum != refundRecord){
                        sendAlarmService.sendAlarmMail(Constant.ALARM_MAIL,"【异常】福建农行生活缴费每天晚上对账单处理，退款条数不对",
                                billDate +","+readRefundNum+","+refundRecord);
                    }
                    continue;
                }

                // 按字段位置顺序解析（索引从0开始）
                int index = 0;
                LifepayBillEntity lifepayBill = new LifepayBillEntity();
                lifepayBill.setId(SeqUtil.getSeqId());

                // 基础时间信息
                lifepayBill.setTradeDate(fields.get(index++));
                lifepayBill.setTradeTime(fields.get(index++));
                lifepayBill.setAccountingDate(fields.get(index++));

                // 流水号信息
                lifepayBill.setPaymentSerialNo(fields.get(index++));
                lifepayBill.setEPayOrderNo(fields.get(index++));
                lifepayBill.setTransactionSerialNo(fields.get(index++));

                lifepayBill.setPaymentMerchantNo(fields.get(index++));

                // 缴费项目信息（根据样例调整位置）
                lifepayBill.setPaymentItemCode(fields.get(index++));
                lifepayBill.setPaymentItemName(fields.get(index++));

                // 商户信息
                lifepayBill.setMerchantCode(fields.get(index++));
                lifepayBill.setMerchantName(fields.get(index++));

                // 用户信息
                lifepayBill.setUserId(fields.get(index++));

                // 金额信息（注意顺序调整）
                lifepayBill.setPaymentAmount(fields.get(index++));  // 支付金额
                lifepayBill.setDiscountAmount(fields.get(index++)); // 优惠金额

                // 缴费状态
                lifepayBill.setPaymentStatus(fields.get(index++));

                // 用户输入字段（1-5）
                lifepayBill.setUserInput1(fields.get(index++));
                lifepayBill.setUserInput2(fields.get(index++));
                lifepayBill.setUserInput3(fields.get(index++));
                lifepayBill.setUserInput4(fields.get(index++));
                lifepayBill.setUserInput5(fields.get(index++));

                // 收款账户信息
                lifepayBill.setPayeeMerchantNo(fields.get(index++));
                lifepayBill.setPayeeAccountNo(fields.get(index++));
                lifepayBill.setSplitAccountTemplateNo(fields.get(index++));

                // 付款账号
                lifepayBill.setPayerAccountNo(fields.get(index++));

                // 缴费渠道
                lifepayBill.setPaymentChannel(fields.get(index++));

                // 退款流水号
                lifepayBill.setRefundSerialNo(fields.get(index++));
                lifepayBill.setERefundOrderNo(fields.get(index++));

                // 退款金额
                lifepayBill.setRefundAmount(fields.get(index++));
                lifepayBill.setRefundDiscountAmount(fields.get(index++));

                // 退款状态
                lifepayBill.setRefundStatus(fields.get(index++));

                // 清算模式
                lifepayBill.setSettlementMode(fields.get(index++));

                // 子账单信息
                lifepayBill.setSubBillNo(fields.get(index++));
                lifepayBill.setSubBillName(fields.get(index++));

                System.out.println(JSON.toJSONString(lifepayBill));
                // 收付标识（枚举转换）
                String flag = fields.get(index);
                System.out.println("flag:"+flag+":"+index);
                lifepayBill.setPayRefundFlag(LifepayBillEntity.PaymentRefundFlag.valueOf(flag));
                lifepayBill.setCreateTime(new Date());

                if(LifepayBillEntity.PaymentRefundFlag.PAY_SUCCESS == lifepayBill.getPayRefundFlag()){
                    payRecord ++ ;
                } else {
                    refundRecord ++ ;
                }

                if(lifepayBillList.size()> 2000){
                    lifepayBillService.saveBatch(lifepayBillList);
                    lifepayBillList.clear();
                }
                lifepayBillList.add(lifepayBill);
                totalRecord = totalRecord + 1;
            }

            if(lifepayBillList.size()> 0){
                lifepayBillService.saveBatch(lifepayBillList);
                lifepayBillList.clear();
            }

            return AjaxResult.success("操作成功!");

        } catch (Exception e){
            e.printStackTrace();
            logger.error(e.getMessage());
            sendAlarmService.sendAlarmMail(Constant.ALARM_MAIL,"【异常】福建农行生活缴费每天晚上对账单处理，",billDate+e.getMessage());
            return AjaxResult.error(e.getMessage());
        }
    }

    public void sendResultToMail(){
        String billDate = DateUtil.format(DateUtil.offsetDay(new Date(), -1),"yyyyMMdd");
        String startDt = DateUtil.format(DateUtil.offsetDay(new Date(),-1),"yyyy-MM-dd");
        String endDt = DateUtil.format(new Date(),"yyyy-MM-dd");
        StringBuilder content = new StringBuilder();
        //content.append("对账单时间：").append(billDate);

        BigDecimal orderSuccessAmount = BigDecimal.ZERO;
        BigDecimal orderFail = BigDecimal.ZERO;
        BigDecimal billPayAmount = BigDecimal.ZERO;
        BigDecimal billRefundAmount = BigDecimal.ZERO;

        QueryWrapper<LifepayOrderEntity> wrapper = new QueryWrapper<>();
        List<Map<String, Object>> orderResult = lifepayOrderService.selectLifepayOrderMaps(startDt,endDt);
        for(Map<String, Object> orderMap : orderResult){
            String sumPayBillAmt = orderMap.get("sumPayBillAmt").toString();
            String count = orderMap.get("count").toString();
            String processed = orderMap.get("processed").toString();
            if("2".equals(processed)){
                orderSuccessAmount = orderSuccessAmount.add(new BigDecimal(sumPayBillAmt)).setScale(2, BigDecimal.ROUND_HALF_UP);
                content.append("充值成功金额:").append(sumPayBillAmt).append(",成功笔数：").append(count);
                content.append("\r\n");
            } else if("3".equals(processed)){
                orderFail = orderFail.add(new BigDecimal(sumPayBillAmt)).setScale(2, BigDecimal.ROUND_HALF_UP);
                content.append("充值失败金额:").append(sumPayBillAmt).append(",失败笔数：").append(count);
                content.append("\r\n");
            } else {
                content.append("异常状态：").append(processed).append(",异常充值金额:").append(sumPayBillAmt).append(",异常笔数：").append(count);
                content.append("\r\n");
            }
        }

        List<Map<String, Object>> billResult = lifepayBillService.selectLifepayBillMaps(billDate);
        for(Map<String, Object> billMap : billResult){
            String sumPaymentAmount = billMap.get("sumPaymentAmount").toString();
            String sumRefundAmount = billMap.get("sumRefundAmount").toString();
            String payRefundFlag = billMap.get("pay_refund_flag").toString();
            if("PAY_SUCCESS".equalsIgnoreCase(payRefundFlag)){
                billPayAmount = billPayAmount.add(new BigDecimal(sumPaymentAmount)).setScale(2, BigDecimal.ROUND_HALF_UP);
                content.append("账单成功金额:").append(sumPaymentAmount);
                content.append("\r\n");
            } else if("REFUND_SUCCESS".equalsIgnoreCase(payRefundFlag)){
                billRefundAmount = billRefundAmount.add(new BigDecimal(sumRefundAmount)).setScale(2, BigDecimal.ROUND_HALF_UP);
                content.append("账单退款金额:").append(sumRefundAmount);
                content.append("\r\n");
            }
        }

        BigDecimal orderTotalAmount = orderSuccessAmount.add(orderFail);
        if(orderTotalAmount.compareTo(billPayAmount) == 0 ){
            content.append("账单与充值的结果一致,充值总金额：").append(orderTotalAmount).append(",账单总金额：").append(billPayAmount);
        } else {
            content.append("账单与充值的结果不一致,充值总金额：").append(orderTotalAmount).append(",账单总金额：").append(billPayAmount);
        }
        content.append("\r\n");

        if(billRefundAmount.compareTo(orderFail) == 0 ){
            content.append("退款结果是一致,充值退款:").append(orderFail).append(",账单退款：").append(billRefundAmount);
        } else {
            content.append("退款结果是不一致,充值退款:").append(orderFail).append(",账单退款：").append(billRefundAmount);
        }

        sendAlarmService.sendAlarmMail(Constant.ALARM_MAIL+",rongyidui@qq.com", "福建农行生活缴费"+ billDate +"对账单", content.toString());
    }
}
